package com.example.demo.use_demo.a_excel_demo;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * excel导出工具类
 *
 * @author zhangqiang
 * @date 2021/4/14 17:13
 */
@Slf4j
public class ExcelExportUtilExtHuTool {
    private ExcelExportUtilExtHuTool() {
    }

    /**
     * 导出excel数据
     *
     * @param response    响应
     * @param headers     表头
     * @param headerAlias 表头-别名
     * @param data        数据
     * @param fileName    文件名
     */
    public static void exportHt(HttpServletResponse response, List<String> headers, Map<String, String> headerAlias, Iterable<?> data, String fileName) {
        try {
            OutputStream outputStream = response.getOutputStream();
            ExcelWriter excelWriter = ExcelUtil.getWriter(true);
            excelWriter.writeHeadRow(headers);
            excelWriter.setHeaderAlias(headerAlias);
            excelWriter.write(data);

            String fileNameEncode = URLEncoder.encode(fileName, "utf-8");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileNameEncode);
            excelWriter.flush(outputStream, true);
            excelWriter.close();
            IoUtil.close(outputStream);
        } catch (IOException e) {
            log.error("Excel模板导出异常IOException:{}", e.getMessage());
            throw new RuntimeException("IOException");
        }
    }

    /**
     * 导出excel数据-大量
     *
     * @param response    响应
     * @param headers     表头
     * @param headerAlias 表头-别名
     * @param data        数据
     * @param fileName    文件名
     */
    public static void exportBigDataHt(HttpServletResponse response, List<String> headers, Map<String, String> headerAlias, Iterable<?> data, String fileName) {
        try {
            OutputStream outputStream = response.getOutputStream();
            ExcelWriter bigExcelWriter = ExcelUtil.getBigWriter();
            bigExcelWriter.writeHeadRow(headers);
            bigExcelWriter.setHeaderAlias(headerAlias);
            bigExcelWriter.write(data);

            String fileNameEncode = URLEncoder.encode(fileName, "utf-8");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileNameEncode);
            bigExcelWriter.flush(outputStream, true);
            bigExcelWriter.close();
            IoUtil.close(outputStream);
        } catch (IOException e) {
            log.error("Excel模板导出异常IOException:{}", e.getMessage());
            throw new RuntimeException("IOException");
        }
    }

    /**
     * 下载excel模板
     *
     * @param response       响应
     * @param filePathPrefix 文件路径
     * @param fileName       文件名
     */
    public static void exportTpl(HttpServletResponse response, String filePathPrefix, String fileName) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            ClassPathResource resource = new ClassPathResource(filePathPrefix + fileName);
            inputStream = resource.getInputStream();
            outputStream = response.getOutputStream();
            Workbook workbook = WorkbookFactory.create(inputStream);
            response.setContentType("application/vnd.ms-excel; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "utf-8"));
            response.setCharacterEncoding("utf-8");
            workbook.write(outputStream);
        } catch (Exception e) {
            log.error("导出excel模板文件Exception", e);
            throw new RuntimeException();
        } finally {
            IoUtil.close(inputStream);
            IoUtil.close(outputStream);
        }
    }

    /**
     * 循环查询导出(HuTool)
     */
    public static <D> void exportLoopWriteHt(HttpServletResponse response,
                                             List<String> headers, Map<String, String> headerAlias,
                                             Function<Integer, Collection<D>> dataGetFunction, String fileName) {
        try {
            response.setContentType("application/vnd.ms-excel; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "utf-8"));
            response.setCharacterEncoding("utf-8");
            // 传入一段代码逻辑查询数据,循环写出
            ExcelWriter bigExcelWriter = ExcelUtil.getBigWriter();
            bigExcelWriter.writeHeadRow(headers);
            bigExcelWriter.setHeaderAlias(headerAlias);
            int pageNum = 1;
            while (true) {
                Collection<D> datas = dataGetFunction.apply(pageNum);
                if (CollectionUtil.isNotEmpty(datas)) {
                    bigExcelWriter.write(datas);
                } else {
                    break;
                }
                pageNum++;
            }
            bigExcelWriter.flush(response.getOutputStream(), true);
            bigExcelWriter.close();
        } catch (Exception e) {
            log.error("导出excel文件Exception", e);
            throw new RuntimeException();
        }
    }

    /**
     * 循环查询导出(EasyExcel)
     */
    public static <D> void exportLoopWriteEe(HttpServletResponse response,
                                             Class<D> clazz,Function<Integer, List<D>> dataGetFunction,
                                             String fileName) {
        try {
            response.setContentType("application/vnd.ms-excel; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "utf-8"));
            response.setCharacterEncoding("utf-8");
            com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), clazz).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
            // 传入一段代码逻辑查询数据,循环写出
            int pageNum = 1;
            while (true) {
                List<D> datas = dataGetFunction.apply(pageNum);
                if (CollectionUtil.isNotEmpty(datas)) {
                    excelWriter.write(datas, writeSheet);
                } else {
                    break;
                }
                pageNum++;
            }
            excelWriter.finish();
        } catch (Exception e) {
            log.error("导出excel文件Exception", e);
            throw new RuntimeException();
        }
    }

}
